package com.utc.cards.player.jade.agent.playerAgent;

import jade.core.AID;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.utc.cards.Constants;
import com.utc.cards.common.jade.Mapper;
import com.utc.cards.games.damedepique.DameDePiqueGameBehaviour;
import com.utc.cards.model.game.Info;
import com.utc.cards.model.game.InfoType;
import com.utc.cards.model.player.Hands;
import com.utc.cards.model.player.IPlayer;

public class PlayerPlayCardBehaviour extends Behaviour
{

    private static Logger log = LoggerFactory.getLogger(DameDePiqueGameBehaviour.class);
    private static final long serialVersionUID = 6818283964364858275L;

    private static final String CONVERSATION_ID = "info";

    private PlayerAgent agent;
    private boolean done = false;
    private Hands hand;
    private MessageTemplate template;

    public PlayerPlayCardBehaviour(PlayerAgent playerAgent, Hands hands)
    {
        super(playerAgent);
        this.agent = playerAgent;
        this.hand = hands;
    }

    @Override
    public void onStart()
    {
        // 0: send to rules agent

        log.debug("PlayCardBehaviour : validating cards ...");
        ACLMessage message = new ACLMessage(ACLMessage.INFORM);
        message.setConversationId(CONVERSATION_ID);

        AID aidRuleAgent = new AID(Constants.CARDS_HOST_RULES_AGENT_NAME, AID.ISLOCALNAME);
        log.debug("PlayCardBehaviour : validating cards ... to " + aidRuleAgent.getName());
        message.addReceiver(aidRuleAgent);

        try
        {
            Info info = new Info(InfoType.VALIDATE_CARDS, Mapper.getObjectMapper().writeValueAsString(hand));
            log.debug("PlayCardBehaviour : from {} : {}", agent.getLocalName(), info);
            message.setContent(Mapper.getObjectMapper().writeValueAsString(info));
            agent.send(message);
            template = MessageTemplate.and(MessageTemplate.MatchConversationId("validate-cards"),
                    MessageTemplate.or(MessageTemplate.MatchPerformative(ACLMessage.AGREE), MessageTemplate.MatchPerformative(ACLMessage.REFUSE)));
        }
        catch (JsonProcessingException e)
        {
            log.error("Error while mapping List<String>");
            e.printStackTrace();
        }
    }

    @Override
    public void action()
    {

        // 1: wait for response

        ACLMessage message = agent.receive(template);
        if (message != null)
        {
            if (message.getPerformative() == ACLMessage.AGREE)
            {
                log.debug("Carte acceptée");
                // Stop du tour du joueur
                agent.onPlayerTurnStop();

                // retrait des cartes de la vue
                agent.getModel().getPlayer().getHand().removeAll(hand.get(IPlayer.MAIN_HAND));

                // mise a jour de la vue
                agent.onCardsChanged(hand, InfoType.REMOVE_CARDS);

                // nouveau message pour game agent pour mettre à jour le hostmodel et passer au joueur suivant
                playCards();
            }
            else if (message.getPerformative() == ACLMessage.REFUSE)
            {
                log.debug("Carte refusée");
                // on ne fait rien, le joueur peut encore tenter de jouer une carte
                // l'ia demande toujours à valider une carte conseillée donc valide
            }
            done = true;
        }
        // si ACL.AGREE alors retrait de la vue des cartes et envoi à GameAgent
        // si ACL.REFUSE alors rien
        block();
    }

    private void playCards()
    {
        log.debug("PlayCardBehaviour : {} is playing cards ...", agent.getLocalName());
        ACLMessage message = new ACLMessage(ACLMessage.REQUEST);
        message.setConversationId("game");
        message.addReceiver(new AID(Constants.CARDS_HOST_GAME_AGENT_NAME, AID.ISLOCALNAME));
        try
        {
            Info info = new Info(InfoType.PLAY_CARDS, Mapper.getObjectMapper().writeValueAsString(hand));
            log.debug("PlayCardBehaviour : {} is playing cards {}", agent.getLocalName(), info.getJson());
            message.setContent(Mapper.getObjectMapper().writeValueAsString(info));
            agent.send(message);
        }
        catch (JsonProcessingException e)
        {
            log.error("Error while mapping Map<String, Deck>");
            e.printStackTrace();
        }
    }

    @Override
    public boolean done()
    {
        return done;
    }

}
